package org.example.business_logic.action;

import javafx.util.Pair;
import lombok.AllArgsConstructor;
import org.example.business_logic.component.Ball;
import org.example.business_logic.component.Hole;
import org.example.physics_engine.collision.CollisionFilter;
import org.example.physics_engine.collision.detector.BasicCollisionDetector;
import org.example.physics_engine.collision.detector.DetectorResult;
import org.example.physics_engine.collision.detector.DetectorUtil;
import org.example.physics_engine.collision.manifold.Manifold;
import org.example.physics_engine.body.PhysicsBody;
import org.example.physics_engine.geometry.Vector2d;
import org.example.facade.panel.GizmoPhysicsBody;

import java.util.ArrayList;
import java.util.List;


@AllArgsConstructor
public class HoleAction implements UpdateListener {
    private final List<PhysicsBody> balls;//如果是引用类型的变量，则在对其初始化之后便不能再让其指向另一个对象。
    private final List<PhysicsBody> holes;
    private final List<GizmoPhysicsBody> allBodies;

    private final BasicCollisionDetector basicCollisionDetector = new BasicCollisionDetector(){
        /**
         * bodies1是ball，bodies2是hole
         * @param bodies1
         * @param bodies2
         * @param filters
         * @return 碰撞的流形信息
         */
        @Override
        public List<Pair<Manifold,Pair<PhysicsBody, PhysicsBody>>> detect(List<PhysicsBody> bodies1, List<PhysicsBody> bodies2, List<CollisionFilter> filters){
            List<Pair<Manifold,Pair<PhysicsBody,PhysicsBody>>> manifolds=new ArrayList<>();
            for(PhysicsBody body1:bodies1){
                Ball ball=(Ball) body1.getShape();
                for(PhysicsBody body2:bodies2){
                    Hole hole=(Hole) body2.getShape();
                    gravityAccumulation(body1,body2);//算重力
                    DetectorResult detectorResult= DetectorUtil.circleDetect(ball,hole,null,null);
                    if(detectorResult.isHasCollision()){
                        manifolds.add(new Pair<>(null,new Pair<>(body1,body2)));                    }
                }
            }
            return manifolds;
        }

        private void gravityAccumulation(PhysicsBody body1,PhysicsBody body2){
            Vector2d bc1=new Vector2d(body1.getShape().getTransform().getX(), body1.getShape().getTransform().getY());
            Vector2d bc2=new Vector2d(body2.getShape().getTransform().getX(), body2.getShape().getTransform().getY());
            Vector2d force=bc1.to(bc2);
            double r=force.getMagnitude();//得到力的大小？
            force.normalize();
            Hole hole=(Hole) body2.getShape();
            force.multiplyNum(body1.getMass().getMass()*hole.getRadius()*10000/r/r);//第一个getMass是得到mass类，然后再得到质量的数值
            body1.getForces().add(force);//加到小球当前所受力的列表

        }
    };

    /**
     * 每个tick检查黑洞是否和小球碰撞
     */
    @Override
    public List<Pair<Manifold, Pair<PhysicsBody, PhysicsBody>>> tick(){
        for(PhysicsBody ball:balls){
            ball.getForces().clear();
        }
        List<Pair<Manifold, Pair<PhysicsBody, PhysicsBody>>> detect=basicCollisionDetector.detect(balls,holes,null);//调用这个类里面重写的basicCollisionDetect的

        for(Pair<Manifold, Pair<PhysicsBody, PhysicsBody>> pair:detect){
            PhysicsBody ball=pair.getValue().getKey();//得到pair中的第一个physicsBody
            balls.remove(ball);
            allBodies.remove(ball);
        }
        return new ArrayList<>();//只是为了和接口的返回值能匹配
    }
}
